package by.cooker.chat.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;

import javax.swing.AbstractAction;
import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;

import by.cooker.chat.logic.Configuration;
import by.cooker.chat.logic.Formater;
import by.cooker.chat.logic.Sender;
import by.cooker.chat.logic.listeners.ConnectAction;

/**
 * @author cooker
 */
public final class Window extends JFrame
{
	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	private JPanel bot;
	private JPanel center;
	private Color guiBackground;
	private Font guiFont;

	private Color guiForeground;
	private JTextField inputField;
	private JPanel left;

	private MessagesArea messagesArea;
	private Sender sender;
	private SimpleAttributeSet textColor;

	private Properties themeProps;

	private JPanel top;
	private JList usersList;

	private String yourName;

	private SimpleAttributeSet yourNameColor;

	/**
	 * Window constructor.
	 */
	public Window()
	{
		setSize(new Dimension(700, 600));
		intialize();
	}

	public Color getGuiBackground()
	{
		if (guiBackground == null)
		{
			guiBackground = Color.decode(getThemeProperties().getProperty(
					"background"));
		}
		return guiBackground;
	}

	public Font getGuiFont()
	{
		if (guiFont == null)
		{
			guiFont = new Font(getThemeProperties().getProperty("name"),
					Font.PLAIN, Integer
							.parseInt(themeProps.getProperty("size")));
		}
		return guiFont;
	}

	public Color getGuiForeground()
	{
		if (guiForeground == null)
		{
			guiForeground = Color.decode(getThemeProperties().getProperty(
					"foreground"));
		}
		return guiForeground;
	}

	public String getYourName()
	{
		if(yourName == null)
		{
			yourName = Configuration.getConf().getString("login");
		}
		return yourName;
	}


	/**
	 * Get input field.
	 *
	 * @return input field.
	 */
	public JTextField getInput()
	{
		if (inputField == null)
		{
			inputField = new JTextField()
			{
				/**
				 *
				 */
				private static final long serialVersionUID = 1L;

				@Override
				public void paintComponent(Graphics g)
				{
					Graphics2D g2d = (Graphics2D) g;
					g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
							RenderingHints.VALUE_ANTIALIAS_ON);
					super.paintComponent(g);
				}
			};
			inputField.setFont(getGuiFont());
			inputField.setBackground(getGuiBackground());
			inputField.setForeground(getGuiForeground());
			inputField.setEditable(true);
			inputField.addKeyListener(new KeyAdapter()
			{
				@Override
				public void keyPressed(KeyEvent e)
				{
					if (e.getKeyCode() == KeyEvent.VK_ENTER)
					{
						String messageText = inputField.getText();
						inputField.setText(null);

						if (messageText.charAt(0) != '/')
						{
							printToOutput(messageText);
						}
						getSender().sendMsg(messageText);
					}
				}

				/**
				 * Print message to messages area.
				 *
				 * @param messageText
				 */
				private void printToOutput(String messageText)
				{
					StringBuilder sb = new StringBuilder();
					sb.append("(");
					sb.append(Formater.getTime());
					sb.append(") ");
					sb.append(getYourName());
					sb.append(": ");
					messagesArea.appendText(sb.toString(), getYourNameColor());
					sb.setLength(0);
					sb.append(messageText);
					sb.append("\n");
					messagesArea.appendText(sb.toString(), getTextColor());
					sb.setLength(0);
				}
			});
		}
		return inputField;
	}

	/**
	 * Get messages area.
	 *
	 * @return messages area.
	 */
	public MessagesArea getMessagesArea()
	{
		if (messagesArea == null)
		{
			messagesArea = new MessagesArea()
			{
				/**
				 *
				 */
				private static final long serialVersionUID = 1L;

				@Override
				public void paintComponent(Graphics g)
				{
					Graphics2D g2d = (Graphics2D) g;
					g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
							RenderingHints.VALUE_ANTIALIAS_ON);
					super.paintComponent(g);
				}
			};
			messagesArea.setEditable(false);
			messagesArea.setDoubleBuffered(true);
			messagesArea.setAutoscrolls(true);
			messagesArea.setFont(getGuiFont());
			messagesArea.setBackground(getGuiBackground());
		}
		return messagesArea;
	}

	/**
	 * Get sender.
	 *
	 * @return sender.
	 */
	private Sender getSender()
	{
		if (sender == null)
		{
			try
			{
				sender = new Sender();
			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		return sender;
	}

	public SimpleAttributeSet getTextColor()
	{
		if (textColor == null)
		{
			textColor = new SimpleAttributeSet();
			StyleConstants.setForeground(textColor, Color
					.decode(getThemeProperties().getProperty("text")));
		}
		return textColor;
	}

	/**
	 * Get properties.
	 *
	 * @return properties.
	 */
	public Properties getThemeProperties()
	{
		if (themeProps == null)
		{
			themeProps = new Properties();
			try
			{
				FileInputStream stream = new FileInputStream(new File(
						Configuration.getConf().getString("theme.file")));
				themeProps.load(stream);
				stream.close();
			} catch (FileNotFoundException e)
			{
				e.printStackTrace();
			} catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		return themeProps;
	}

	/**
	 * Get users list.
	 *
	 * @return users list.
	 */
	public JList getUsersList()
	{
		if (usersList == null)
		{
			usersList = new JList()
			{
				/**
				 *
				 */
				private static final long serialVersionUID = 1L;

				@Override
				public void paintComponent(Graphics g)
				{
					Graphics2D g2d = (Graphics2D) g;
					g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
							RenderingHints.VALUE_ANTIALIAS_ON);
					super.paintComponent(g);
				}
			};
			usersList.setFixedCellWidth(100);
			usersList.setFont(getGuiFont());
			usersList.setForeground(getGuiForeground());
			usersList.setBackground(getGuiBackground());
		}
		return usersList;
	}

	public SimpleAttributeSet getYourNameColor()
	{
		if (yourNameColor == null)
		{
			yourNameColor = new SimpleAttributeSet();
			StyleConstants.setForeground(yourNameColor, Color
					.decode(getThemeProperties().getProperty("you")));
		}
		return yourNameColor;
	}

	/**
	 * Initialize components.
	 */
	private void intialize()
	{
		JPanel content = (JPanel) Window.this.getContentPane();
		regShortCut(content, Configuration.getConf().getString(
				"shortcuts.connect"), "connect", new ConnectAction(Window.this));

		top = new JPanel(new BorderLayout());
		center = new JPanel(new BorderLayout());
		left = new JPanel(new BorderLayout());
		bot = new JPanel(new BorderLayout());

		center.add(new JScrollPane(getMessagesArea()), BorderLayout.CENTER);
		bot.add(getInput(), BorderLayout.CENTER);
		left.add(new JScrollPane(getUsersList()), BorderLayout.CENTER);

		add(top, BorderLayout.NORTH);
		add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, center));
		add(bot, BorderLayout.SOUTH);
		setLocationRelativeTo(null);
	}

	/**
	 * Register short cuts.
	 *
	 * @param component
	 *            component.
	 * @param shorcut
	 *            the short cut.
	 * @param actionMap
	 *            the action map.
	 * @param action
	 *            the action.
	 */
	public void regShortCut(JPanel component, String shortcut,
			Object actionMap, AbstractAction action)
	{
		KeyStroke stroke = KeyStroke.getKeyStroke(shortcut);
		InputMap inputMap = component.getInputMap(JComponent.WHEN_FOCUSED);
		inputMap.put(stroke, actionMap);
		component.getActionMap().put(actionMap, action);
	}

}
